/*
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the FxStruts.
 *
 * The Initial Developer of the Original Code is
 * Anirudh Sasikumar (http://anirudhs.chaosnet.org/).
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
*/
package com.adobe.fxstruts.rpc
{
	import flash.net.getClassByAlias;
	import flash.net.registerClassAlias;
	import flash.utils.ByteArray;
	
	import mx.collections.ArrayCollection;
	import mx.core.mx_internal;
	import mx.messaging.Channel;
	import mx.messaging.ChannelSet;
	import mx.messaging.messages.IMessage;
	import mx.resources.ResourceManager;
	import mx.rpc.AsyncToken;
	import mx.rpc.Fault;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.http.mxml.HTTPService;
	
	use namespace mx_internal;
	
	public class HTTPAMFService extends HTTPService
	{
		private var _type:Class;
		private var _serverType:String;
		private var _numObjects:int;
    	public static const RESULT_FORMAT_AMF:String = "amf";    	
    	
    	protected static var amfChannel:Channel;
    	protected static var amfChannelSet:ChannelSet;
    
		public function HTTPAMFService(rootURL:String=null, destination:String=null)
		{
			super(rootURL, destination);
			_numObjects = 1;
			
		}
		
		[Inspectable]
		public function get returnType():Class
		{
			return _type;	
		}
		
		public function set returnType(str:Class):void
		{
			_type = str;	
		}
		
		[Inspectable]
		public function get serverType():String
		{
			return _serverType;	
		}
		
		public function set serverType(str:String):void
		{
			_serverType = str;	
		}		
		
		[Inspectable]
		public function get numObjects():int
		{
			return _numObjects;	
		}
		
		public function set numObjects(str:int):void
		{
			if ( str < 1 )
			{
	            throw new ArgumentError("Invalid number of return objects");
			}
			_numObjects = str;	
		}
		
		[Inspectable(enumeration="amf", defaultValue="amf", category="General")]
		override public function set resultFormat(value:String):void
	    {
	        switch (value)
	        {
	            case RESULT_FORMAT_AMF:
	            {
	                break;
	            }
	
	            default:
	            {
	                var message:String = ResourceManager.getInstance().getString(
	                    "rpc", "invalidResultFormat",
	                    [ value, RESULT_FORMAT_AMF ]);
	                throw new ArgumentError(message);
	            }
	        }
	        super.resultFormat = RESULT_FORMAT_TEXT;
	    }
	    
	    override public function send(parameters:Object = null):AsyncToken
    	{
    		if ( useProxy == false )
    		{
    			if ( amfChannelSet == null )
    			{
    				var dcs:ChannelSet = new ChannelSet();
    				amfChannel = new DirectHTTPAMFChannel("direct_http_amf_channel");
            		dcs.addChannel(amfChannel);            
            		channelSet = dcs
            		amfChannelSet = dcs;
       			}
       			else if ( channelSet != amfChannelSet )
       			{
       				channelSet = amfChannelSet;
       			}       			
    		}    		
    		return super.send(parameters);	
    	}
    	
	     override mx_internal function processResult(message:IMessage, token:AsyncToken):Boolean
	     {
	     	var body:Object = message.body;
	     	
	     	if (body == null )
        	{
	            _result = body;
	            return true;
        	}
        	else if ( body is ByteArray )
        	{
        		var barr:ByteArray = body as ByteArray;
        		try
				{
					getClassByAlias("flex.messaging.io.ArrayCollection");
				}
				catch ( err:ReferenceError )
				{
					registerClassAlias("flex.messaging.io.ArrayCollection", ArrayCollection);	
				}
        		if ( _type != null && _serverType != null && _serverType.length > 0 )
				{
					try
					{
						getClassByAlias(_serverType);
					}
					catch ( err:ReferenceError )
					{
						registerClassAlias(_serverType, _type);	
					}	
				}
				if ( _numObjects <= 1 )
				{
					try
					{
						var obj:Object = barr.readObject();
						_result = obj;
					}
					catch ( parseError:Error )
					{
						var fault:Fault = new Fault(ERROR_DECODING, parseError.message);
                    	dispatchRpcEvent(FaultEvent.createEvent(fault, token, message));
                    	return false;
					}
				}
				else
				{
					var resarr:ArrayCollection = new ArrayCollection();
					try
					{
						for ( var i:int = 0; i < _numObjects; i++ )
						{
							resarr.addItem(barr.readObject());
						}
						_result = resarr;
					}
					catch ( parseError1:Error )
					{
						var fault1:Fault = new Fault(ERROR_DECODING, parseError1.message);
						if ( resarr.length > 0 )
						{
							/* if ( resarr.length > 1 ) */
								_result = resarr;
							/* else
							{
								_result = resarr.getItemAt(0);
							} */
							return true;
						}
						else
                    		dispatchRpcEvent(FaultEvent.createEvent(fault1, token, message));
                    	return false;
					}
					
				}
				return true;
        	}
	     	return false;
	     }
	}
}